<template>
    <div class="upload-box" :key="key">
        <div class="imgbox" v-if="imgShow" @mouseenter="hoverShow = true" @mouseleave="hoverShow = false">
            <img :src="imgCoverUrl" alt="" />
            <div class="handle-area" v-if="hoverShow">
                <a-icon type="eye" @click="previewFile" title="预览文件" />
                <a-icon v-if="edit" type="delete" @click="deleteFile" title="删除文件" />
            </div>
        </div>
        <a-upload
            v-if="!imgShow && edit"
            :action="$staticUrl"
            list-type="picture"
            :data="uploadData"
            :before-upload="beforeUpload"
            @change="handleChange"
            :showUploadList="false"
        >
            <div class="btn-box">
                <a-icon type="cloud-upload" />
                <span class="ant-upload-text">点击上传</span>
            </div>
        </a-upload>
        <a-modal
            class="videoModal"
            :visible="previewVisible"
            :footer="null"
            @cancel="handleCancel"
            width="40%"
            title="视频预览"
        >
            <video controls id="video">
                <source :src="videoUrl" type="video/mp4" />
                <source :src="videoUrl" type="video/ogg" />
                <source :src="videoUrl" type="video/webm" />
                <object :data="videoUrl">
                    <embed :src="videoUrl" />
                </object>
            </video>
        </a-modal>
    </div>
</template>

<script>
import { getUUID } from '@/plugins/tools'
function getBase64 (file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.readAsDataURL(file)
        reader.onload = () => resolve(reader.result)
        reader.onerror = error => reject(error)
    })
}
// 截取视屏第一帧作为封面图(base64格式) 将base
function getVideoBase64 (url) {
    return new Promise(function (resolve, reject) {
        let dataURL = ''
        const video = document.createElement('video')
        video.setAttribute('crossOrigin', 'anonymous') // 处理跨域
        video.setAttribute('src', url)
        video.setAttribute('width', 400)
        video.setAttribute('height', 262)
        video.setAttribute('preload', 'auto')
        video.addEventListener('loadeddata', function () {
            const canvas = document.createElement('canvas')
            const width = video.width // canvas的尺寸和图片一样
            const height = video.height
            canvas.width = width
            canvas.height = height
            canvas.getContext('2d').drawImage(video, 0, 0, width, height) // 绘制canvas
            dataURL = canvas.toDataURL('image/jpeg') // 转换为base64
            resolve(dataURL)
        })
    })
}

// 将base64转换为blob
function dataURLtoBlob (dataurl) {
    const arr = dataurl.split(',')
    const mime = arr[0].match(/:(.*?);/)[1]
    const bstr = atob(arr[1])
    let n = bstr.length
    const u8arr = new Uint8Array(n)
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
    }
    return new Blob([u8arr], { type: mime })
}
// 将blob转换为file
function blobToFile (theBlob, fileName) {
    theBlob.lastModifiedDate = new Date()
    theBlob.name = fileName
    return theBlob
}

// 将base64转成file文件
function baseToFile (base64Data) {
    const blob = dataURLtoBlob(base64Data)
    const file = blobToFile(blob, 'image/jpeg')
    return file
}

export default {
    model: {
        prop: 'value',
        event: 'change'
    },
    props: {
        value: {
            type: Object,
            default: () => {
                return {}
            }
        },
        path: {
            type: String,
            default: () => {
                return ''
            }
        },
        edit: {
            type: Boolean,
            default: () => {
                return true
            }
        }
    },
    data () {
        return {
            imgShow: false,
            hoverShow: false,
            imgCoverUrl: '',
            uploadData: {
                signature: '',
                'x-cos-security-token': '',
                'Content-Type': '',
                key: '',
                dir: '',
                host: ''
            },
            videoUrl: '',
            previewVisible: false,
            key: 0
        }
    },
    watch: {
        value: {
            deep: true,
            immediate: true,
            handler (val) {
                const { videoUrl, imgCoverUrl } = val
                if (videoUrl && imgCoverUrl) {
                    this.videoUrl = this.$staticUrl + videoUrl
                    this.imgCoverUrl = this.$staticUrl + imgCoverUrl
                    this.imgShow = true
                    this.key++
                } else {
                    this.videoUrl = ''
                    this.imgCoverUrl = ''
                    this.imgShow = false
                    this.key++
                }
            }
        }
    },
    methods: {
        beforeUpload (file) {
            return new Promise((resolve, reject) => {
                const typeList = ['video/mp4', 'video/ogg', 'video/webm']
                const uploadPolicy = () => {
                    if (!typeList.includes(file.type)) {
                        this.$message.error('上传视频格式不对!')
                        return false
                    }
                    const isLt4M = file.size / 1024 / 1024 < 50
                    if (!isLt4M) {
                        this.$message.error('视频大小不能超过50M!')
                        return false
                    }
                    const _path = this.path + this.$service.dateFormatter('yyyy-MM-dd') + '/'
                    this.$service.getAuthor({ Method: 'POST', Pathname: '/' }).then((info) => {
                        this.uploadData.signature = info.Authorization
                        this.uploadData['x-cos-security-token'] = info.XCosSecurityToken
                        this.uploadData['Content-Type'] = ''
                        this.uploadData.key = _path + getUUID() + '.' + file.name.replace(/,/g, '').split('.').pop()
                        this.uploadData.dir = _path
                        this.uploadData.host = this.$staticUrl
                        resolve(true)
                    })
                }
                uploadPolicy()
            })
        },
        async handleChange ({ file, fileList }) {
            if (file.status === 'uploading') {
                return
            }
            if (file.status === 'done') {
                if (!file.url && !file.preview) {
                    file.preview = await getBase64(file.originFileObj)
                }
                const videoSrc = file.url || file.preview
                // 将视频第一帧转成jpeg格式的图片
                const imgUrl = await getVideoBase64(videoSrc)
                const fileImg = baseToFile(imgUrl)
                // 手动上传到腾讯云
                const _path = '/' + 'video-cover' + '/' + this.$service.dateFormatter('yyyy-MM-dd') + '/'
                this.$service
                    .getAuthor({ Method: 'POST', Pathname: '/' })
                    .then((info) => {
                        const formData = new FormData()
                        const _key = _path + getUUID() + '.' + fileImg.type
                        formData.append('signature', info.Authorization)
                        formData.append('x-cos-security-token', info.XCosSecurityToken)
                        formData.append('Content-Type', '')
                        formData.append('key', _key)
                        formData.append('dir', _path)
                        formData.append('host', this.$staticUrl)
                        formData.append('file', fileImg)
                        this.$ApiServer
                            .uploadFileCos(formData)
                            .then((res) => {
                                if (res === '') {
                                    const temp = this.uploadData.key
                                    const imgCoverUrl = _key
                                    this.$emit('change', { videoUrl: temp, imgCoverUrl })
                                } else {
                                    this.$message.error('上传失败')
                                }
                            })
                            .catch(() => {
                                this.$message.error('上传失败')
                            })
                    })
                    .catch(() => {
                        this.$message.error('上传失败')
                    })
            }
        },
        previewFile () {
            this.previewVisible = true
        },
        deleteFile () {
            const that = this
            return new Promise((resolve, reject) => {
                this.$confirm({
                    title: '提示',
                    content: '您确认要删除该视频重新上传吗？',
                    okText: '确认',
                    okType: 'primary',
                    cancelText: '取消',
                    onOk () {
                        that.$emit('change', { videoUrl: '', imgCoverUrl: '' })
                    },
                    onCancel () {
                        return resolve(false)
                    }
                })
            })
        },
        handleCancel () {
            const videoDom = document.querySelector('#video')
            videoDom.pause()
            this.previewVisible = false
        }
    }
}
</script>

<style lang="less" scoped>
.upload-box {
    width: 2rem;
    height: 1.4rem;
    display: flex;
    justify-content: center;
    align-items: center;
    .imgbox {
        width: 100%;
        height: 100%;
        border-radius: 4px;
        overflow: hidden;
        position: relative;
        img {
            width: 100%;
            height: 100%;
            position: relative;
            z-index: 1;
            object-fit: cover;
        }
        .handle-area {
            width: 100%;
            height: 100%;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 2;
            background: rgba(0, 0, 0, 0.5);
            display: flex;
            justify-content: center;
            align-items: center;
            i {
                color: rgba(255, 255, 255, 0.85);
                font-size: 16px;
                cursor: pointer;
                & + i {
                    margin-left: 10px;
                }
            }
        }
    }
    & > span {
        display: block;
        width: 100%;
        height: 100%;
        border-radius: 4px;
        border: 1px solid #d4d4d4;
        cursor: pointer;
        &:hover {
            border: 1px solid @primary-color;
            ::v-deep {
                .anticon-cloud-upload svg {
                    color: @primary-color;
                }
                .ant-upload-text {
                    color: @primary-color !important;
                }
            }
        }
        ::v-deep {
            .ant-upload {
                width: 100%;
                height: 100%;
                display: flex;
                justify-content: center;
                align-items: center;
            }
            .btn-box {
                display: flex;
                justify-content: center;
                align-items: center;
                flex-direction: column;
                width: 100%;
                height: 100%;
                .anticon-cloud-upload {
                    color: #999999;
                    font-size: 0.3rem;
                }
                .ant-upload-text {
                    color: #999999;
                    font-size: 0.14rem;
                    margin-top: 6px;
                }
            }
        }
    }
}
.videoModal {
    #video {
        width: 100%;
        height: 400px;
    }
}
</style>
